#include <atomic>
#include <chrono>
#include <cstring>
#include <fstream>
#include <future>
#include <thread>
#include <vector>
#include "gtest/gtest.h"
#define private public
#include "async_logger.h"
#undef private
#include "console_output_strategy.h"
#include "double_buffer.h"
#include "lock_free_ring_buffer.h"

#define UNUSED(x) (void)(x)

namespace Base {
namespace SystemLog {
using namespace std::chrono_literals;
namespace {
const char TEST_CHAR = 't';
const char* TEST_MESSAGE = "Test message";
constexpr int TEST_THREADS = 16;
constexpr int TEST_MESSAGES_COUNT = 10000;
constexpr size_t TEST_MESSAGE_SIZE = 128;
constexpr size_t TEST_MB = 1024 * 1024;    // 1MB
constexpr size_t TEST_BUFFER_SIZE = 1 * TEST_MB;    // 1MB
constexpr uint32_t TEST_FLUSH_INTERVAL_MS = 50;   // 50ms
constexpr size_t TEST_SOFT_FLUSH_THRESHOLD = TEST_BUFFER_SIZE / 2;  // 0.5MB
constexpr size_t TEST_HARD_FLUSH_THRESHOLD = TEST_BUFFER_SIZE * 8 / 10; // 0.8MB

class PerfTimer {
public:
    PerfTimer() : start_(std::chrono::high_resolution_clock::now()) {}

    double elapsed() const {
        auto end = std::chrono::high_resolution_clock::now();
        return std::chrono::duration<double>(end - start_).count();
    }

    std::chrono::nanoseconds elapsed_ns() const {
        auto end = std::chrono::high_resolution_clock::now();
        return end - start_;
    }

private:
    std::chrono::time_point<std::chrono::high_resolution_clock> start_;
};

class TestOutput {
public:
    ErrCode operator()(const char* data, size_t len) {
        std::lock_guard<std::mutex> lock(mutex_);
        output_.append(data, len);
        totalBytes_ += len;
        return ERR_OK;
    }

    const std::string &GetOutput() {
        std::lock_guard<std::mutex> lock(mutex_);
        return output_;
    }

    size_t GetTotalBytes() {
        std::lock_guard<std::mutex> lock(mutex_);
        return totalBytes_;
    }

    void SetTotalBytes(size_t totalBytes) {
        std::lock_guard<std::mutex> lock(mutex_);
        totalBytes_ = totalBytes;
    }

private:
    std::string output_;
    size_t totalBytes_ = 0;
    std::mutex mutex_;
};

} // namespace

class AsyncLoggerTest : public testing::Test {
protected:
    static void SetUpTestCase(void);
    static void TearDownTestCase(void);
    void SetUp();
    void TearDown();
    std::unique_ptr<AsyncLogger<TEST_BUFFER_SIZE>> logger_;
    std::shared_ptr<TestOutput> testOutput_;
};

void AsyncLoggerTest::SetUpTestCase(void)
{}

void AsyncLoggerTest::TearDownTestCase(void)
{}

void AsyncLoggerTest::SetUp()
{
    testOutput_ = std::make_shared<TestOutput>();
    auto task = [this](const char* data, size_t len) -> ErrCode {
        return (*testOutput_)(data, len);
    };
    logger_ = std::make_unique<AsyncLogger<TEST_BUFFER_SIZE>>(task);

    logger_->SetFlushInterval(TEST_FLUSH_INTERVAL_MS);
    logger_->SetFlushThreshold(TEST_SOFT_FLUSH_THRESHOLD, TEST_HARD_FLUSH_THRESHOLD);
    logger_->Start();
}

void AsyncLoggerTest::TearDown()
{
    if (logger_) {
        logger_->Stop();
    }
}

/**
 * @tc.name: AsyncLoggerTest_001
 * @tc.desc: verify basic append and flush operations
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_001)
{
    EXPECT_EQ(logger_->Append(TEST_MESSAGE, std::strlen(TEST_MESSAGE)), ERR_OK);

    std::this_thread::sleep_for(std::chrono::milliseconds(TEST_FLUSH_INTERVAL_MS));
    EXPECT_EQ(logger_->Flush(), ERR_OK);
    auto output = testOutput_->GetOutput();
    EXPECT_NE(output.find(TEST_MESSAGE), std::string::npos);
}

/**
 * @tc.name: AsyncLoggerTest_002
 * @tc.desc: verify flush interval and threshold
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_002)
{
    const std::string smallMsg(TEST_MESSAGE_SIZE * 10, TEST_CHAR);
    const int32_t messagesToFill = static_cast<int32_t>(TEST_SOFT_FLUSH_THRESHOLD / smallMsg.size()) + 1;
    for (int i = 0; i < messagesToFill; ++i) {
        logger_->Append(smallMsg.c_str(), smallMsg.size());
    }
    std::this_thread::sleep_for(std::chrono::milliseconds(TEST_FLUSH_INTERVAL_MS - 10));
    EXPECT_GE(testOutput_->GetTotalBytes(), static_cast<size_t>(messagesToFill) * smallMsg.size());
    
    auto output = testOutput_->GetOutput();
    output.clear();
    testOutput_->SetTotalBytes(0);
    logger_->Append(TEST_MESSAGE, std::strlen(TEST_MESSAGE));
    std::this_thread::sleep_for(std::chrono::milliseconds(TEST_FLUSH_INTERVAL_MS + 10));
    EXPECT_GT(testOutput_->GetTotalBytes(), static_cast<size_t>(0));
}

/**
 * @tc.name: AsyncLoggerTest_003
 * @tc.desc: verify big message
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_003)
{
    const size_t bigMessageSize = TEST_BUFFER_SIZE * 5;
    std::string big_message(bigMessageSize, TEST_CHAR);
    ErrCode err = logger_->Append(big_message.c_str(), bigMessageSize);
    EXPECT_EQ(err, ERR_OK);
    std::this_thread::sleep_for(std::chrono::milliseconds(TEST_FLUSH_INTERVAL_MS + 10));
    EXPECT_EQ(testOutput_->GetTotalBytes(), static_cast<size_t>(TEST_BUFFER_SIZE * 5));
}

/**
 * @tc.name: AsyncLoggerTest_004
 * @tc.desc: verify emergency flush during shutdown
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_004)
{
    logger_->Append(TEST_MESSAGE, std::strlen(TEST_MESSAGE));
    logger_->Stop();
    auto output = testOutput_->GetOutput();
    EXPECT_NE(output.find(TEST_MESSAGE), std::string::npos);
}

/**
 * @tc.name: AsyncLoggerTest_005
 * @tc.desc: verify double buffer swap mechanism
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_005)
{
    logger_->Append(TEST_MESSAGE, std::strlen(TEST_MESSAGE));
    logger_->Flush();
    EXPECT_EQ(logger_->doubleBuffer_.GetFrontSize(), static_cast<size_t>(0));
    EXPECT_GT(testOutput_->GetTotalBytes(), static_cast<size_t>(0));
}

/**
 * @tc.name: AsyncLoggerTest_006
 * @tc.desc: verify AsyncLogger buffer statistics monitoring
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_006) {
    auto& logger = AsyncLogger<TEST_BUFFER_SIZE>::GetInstance();
    
    // 添加控制台输出策略
    auto consoleStrategy = std::make_unique<ConsoleOutputStrategy>();
    logger.AddOutputStrategy(std::move(consoleStrategy));
    
    ASSERT_EQ(logger.Start(), ERR_OK);
    
    // 初始统计
    auto stats = logger.GetBufferStats();
    EXPECT_EQ(stats.frontBufferSize, static_cast<size_t>(0));
    EXPECT_EQ(stats.backBufferSize, static_cast<size_t>(0));
    
    // 写入一些日志
    for (int i = 0; i < 100; ++i) {
        std::string msg = "Test message " + std::to_string(i) + "\n";
        logger.Append(msg.c_str(), msg.length());
    }
    
    // 检查统计信息更新
    stats = logger.GetBufferStats();
    EXPECT_GT(stats.frontBufferSize, static_cast<size_t>(0));
    EXPECT_GT(stats.totalNodes, static_cast<size_t>(0));
    
    logger.Stop();
}

/**
 * @tc.name: AsyncLoggerTest_007
 * @tc.desc: verify AsyncLogger configuration update functionality
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_007) {
    auto& logger = AsyncLogger<TEST_BUFFER_SIZE>::GetInstance();
    
    // 创建新配置
    LoggerConfig newConfig;
    newConfig.flushIntervalMs = 500;
    newConfig.softFlushThreshold = 1024;
    newConfig.hardFlushThreshold = 2048;
    newConfig.minLogLevel = LOG_LEVEL_WARN;
    
    // 更新配置（在停止状态下）
    EXPECT_EQ(logger.UpdateConfig(newConfig), ERR_OK);
    
    // 验证配置已更新
    EXPECT_EQ(logger.flushInterval_.count(), static_cast<long>(500));
    EXPECT_EQ(logger.softFlushThreshold_, static_cast<size_t>(1024));
    EXPECT_EQ(logger.hardFlushThreshold_, static_cast<size_t>(2048));
    EXPECT_EQ(logger.minLogLevel_, LOG_LEVEL_WARN);
}

/**
 * @tc.name: AsyncLoggerTest_008
 * @tc.desc: verify invalid configuration handling
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_008) {
    auto& logger = AsyncLogger<TEST_BUFFER_SIZE>::GetInstance();
    
    // 创建无效配置
    LoggerConfig invalidConfig;
    invalidConfig.flushIntervalMs = 0; // 无效
    
    EXPECT_EQ(logger.UpdateConfig(invalidConfig), ERR_INVALID_ARGUMENT);
}

/**
 * @tc.name: AsyncLoggerTest_009
 * @tc.desc: verify AsyncLogger message filtering
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_009) {
    auto& logger = AsyncLogger<TEST_BUFFER_SIZE>::GetInstance();
    
    // 添加控制台输出策略
    auto consoleStrategy = std::make_unique<ConsoleOutputStrategy>();
    logger.AddOutputStrategy(std::move(consoleStrategy));
    
    ASSERT_EQ(logger.Start(), ERR_OK);
    
    // 设置过滤器 - 过滤掉包含"FILTERED"的消息
    logger.SetFilter([](LogLevel, const char* message, const char*) {
        return strstr(message, "FILTERED") == nullptr;
    });
    
    // 获取初始统计
    auto initialStats = logger.GetBufferStats();
    (void)initialStats; // 避免未使用变量警告
    
    // 发送应该被过滤的消息
    logger.Append("This FILTERED message should not appear\n", 40, LOG_LEVEL_INFO);
    
    // 发送正常消息
    logger.Append("This normal message should appear\n", 34, LOG_LEVEL_INFO);
    
    // 强制刷新
    logger.Flush();
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    
    // 过滤器应该阻止了一条消息，所以缓冲区大小增长应该较小
    auto finalStats = logger.GetBufferStats();
    (void)finalStats; // 避免未使用变量警告
    // 这里主要验证过滤器被调用了，具体的过滤效果在实际输出中验证
    
    logger.Stop();
}

/**
 * @tc.name: AsyncLoggerTest_010
 * @tc.desc: verify AsyncLogger sampling functionality
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_010) {
    auto& logger = AsyncLogger<TEST_BUFFER_SIZE>::GetInstance();
    
    // 设置DEBUG级别0%采样率（全部过滤）
    logger.SetSamplingRate(LOG_LEVEL_DEBUG, 0.0);
    // 设置INFO级别100%采样率（全部通过）
    logger.SetSamplingRate(LOG_LEVEL_INFO, 1.0);
    
    // 验证采样率设置
    EXPECT_DOUBLE_EQ(logger.GetSamplingRate(LOG_LEVEL_DEBUG), 0.0);
    EXPECT_DOUBLE_EQ(logger.GetSamplingRate(LOG_LEVEL_INFO), 1.0);
    EXPECT_DOUBLE_EQ(logger.GetSamplingRate(LOG_LEVEL_WARN), 1.0); // 默认值
}

/**
 * @tc.name: AsyncLoggerTest_011
 * @tc.desc: verify AsyncLogger log level filtering
 * @tc.type: FUNC
 */
TEST_F(AsyncLoggerTest, AsyncLoggerTest_011) {
    auto& logger = AsyncLogger<TEST_BUFFER_SIZE>::GetInstance();
    
    // 添加控制台输出策略
    auto consoleStrategy = std::make_unique<ConsoleOutputStrategy>();
    logger.AddOutputStrategy(std::move(consoleStrategy));
    
    ASSERT_EQ(logger.Start(), ERR_OK);
    
    // 设置最小日志级别为WARN
    logger.SetMinLevel(LOG_LEVEL_WARN);
    
    auto initialStats = logger.GetBufferStats();
    (void)initialStats; // 避免未使用变量警告
    
    // 发送低于最小级别的消息（应该被过滤）
    EXPECT_EQ(logger.Append("DEBUG message\n", 14, LOG_LEVEL_DEBUG), ERR_OK);
    EXPECT_EQ(logger.Append("INFO message\n", 13, LOG_LEVEL_INFO), ERR_OK);
    
    // 发送高于最小级别的消息
    EXPECT_EQ(logger.Append("WARN message\n", 13, LOG_LEVEL_WARN), ERR_OK);
    EXPECT_EQ(logger.Append("ERROR message\n", 14, LOG_LEVEL_ERROR), ERR_OK);
    
    logger.Stop();
}
} // namespace SystemLog
} // namespace Base
